問題解説: VXLANつながらない

問題文

VXLANでの通信を検証するように依頼された。
異なるサーバ上のVXLANインターフェースがお互いに通信できるようにしてほしいとのことだ。サーバ同士はソフトウェアルータを介してL3の疎通性がある。VXLANのアンダーレイ通信には、マルチキャストルーティングを利用してほしいそうだ。
前任者も設定を行ったようなのだが、上手くいかずに諦めてしまったらしい。どうにか設定を変更して、VXLANインターフェース同士が通信できるようにしてほしい。

制約

VXLANインターフェース間の通信は、マルチキャストルーティングを用いたVXLAN通信でなければならない。

スタート地点

Server 1/2のVXLANインターフェース vxlan42 から Server 2/1のVXLANインターフェース vxlan42ping が通らない。

ゴール地点

Server 1/2のVXLANインターフェース vxlan42 から Server 2/1のVXLANインターフェース vxlan42ping が通る。

トラブルの概要

「VXLANが繋がらない」は、L2延伸技術であるVXLANを用います。VXLANは、パケットをカプセル化することでL3ネットワークを超えてL2ネットワークを構成します。
この問題のトポロジーは以下のようになっています。

2台のVMが異なるL2ネットワークに属しており、VyOSによってルーティングされます。それぞれのVMの中にはVXLAN用のインターフェースがあり、これらは仮想的に同じL2ネットワークにあります。
この図のvxlan42から出たパケットがens3でカプセル化され、もう一方のVMのens3を通ってvxlan42に届き、カプセル化が解除されます。
VMのens3とVyOSによって作られるL3ネットワークをアンダーレイ、vxlan42によって作られるL2ネットワークをオーバーレイと呼びます。
一般に、VXLANでは、アンダーレイでのブロードキャストをオーバーレイでのマルチキャストで実装します。ブロードキャストはARPに必要です。オーバーレイがL3ネットワークなので、マルチキャストルーティングを行う必要があります。

この問題では、vxlan42同士が通信できないというトラブルが起こっています。 .67 の方のVMで以下を実行しても疎通が取れません。

$ ping -I vxlan42 10.0.0.3

解説

この問題で起こっているトラブルには要因が2つあります。
– vxlan42 から送られるパケットの TTL が 1 になっている
– VyOS がマルチキャストルーティングを扱えない

TTLについては、VMのVXLANインターフェースが原因です。VXLANインターフェースにTTLを明示的に設定しない場合、TTLが1のパケットが送信されます。 TTLはルーティングの度にデクリメントされ、0になるとパケットが破棄されてしまいます。そこで、VXLANインターフェースの設定を変更する必要があります。

VXLANはマルチキャストルーティングを用いると述べました。実際には、マルチキャストを用いない例もあるのですが、この問題ではマルチキャストを使うよう制約を設けました。ところが、VyOSの config をどのように設定してもマルチキャストルーティングを行うことができません。そのような設定項目がないからです。この問題では VyOS 1.1.7 を使っていますが、私の知る限りは設定方法がありません。
VyOSがマルチキャストルーティングを行うことができないので、パケットが破棄されてしまいます。
しかし、VyOSはDebianをベースにしたソフトウェアルータなので、様々な外部のパッケージを導入することができます。これにより、マルチキャストルーティングを行うことができるようになります。

解答例

まずはVMのVXLANインターフェースのTTLを増やします。
今回、VMのOSはUbuntu 16.04です。はじめ、/etc/network/interfaces に以下のようにVXLANインターフェースの設定が書いてあります。

auto vxlan42
iface vxlan42 inet manual
    pre-up ip link add vxlan42 type vxlan id 42 group 239.255.255.255 || true
    up ip address add 10.0.0.2/24 dev vxlan42 && ip link set vxlan42 up
    down ip link set vxlan42 down
    post-down ip link del vxlan42 || true

これを下記のように書き換えます。

auto vxlan42
iface vxlan42 inet manual
    pre-up ip link add vxlan42 type vxlan id 42 group 239.255.255.255 ttl 2 || true
    up ip address add 10.0.0.2/24 dev vxlan42 && ip link set vxlan42 up
    down ip link set vxlan42 down
    post-down ip link del vxlan42 || true

追加した項目は2行目の ttl 2 のみです。これで送信するパケットのTTLが設定されます。今回はルータを1台はさむ構成なので、TTLが2以上であれば良いです。

$ sudo service networking restart

以上のコマンドを実行すれば設定が反映されます。

続いて、VyOSがマルチキャストルーティングできるようにします。
これはあくまで一例ですが、以下のようにして、外部のリポジトリを登録します。

$ conf
$ set system package repository squeeze components 'main contrib non-free'
$ set system package repository squeeze distribution 'squeeze'
$ set system package repository squeeze url 'http://archive.debian.org/debian'
$ commit; save

ただし、このままでは以下のコマンドでのパッケージのアップデートに失敗します。

$ sudo aptitude update

これは、DNSサーバが設定されていないためです。

$ vi /etc/resolve.conf
nameserver 8.8.8.8

このように /etc/resolve.conf などを修正すれば、アップデートが実行できるようになります。
そして、マルチキャストルーティングのプロトコルであるPIMを扱うために、PIMDをインストールします。

$ sudo aptitude install pimd

インストールすれば自動的にプロセスが立ち上がり、マルチキャストルーティングが動作するようになります。ただし、インストールしてから動作するまでは少し時間がかかります。

以上の項目を完了すれば、以下のコマンドで疎通が取れるはずです。

$ ping -I vxlan42 10.0.0.3

講評

この問題を完全に解くことができたのは1チームだけでした。

余談

ちなみに、この問題はICTSC 8の運営での経験から思いつきました。ICTSC 8ではVXLANを使うことで、Mと手元機材が同じL2ネットワークにあるように見せました。この際、アンダーレイはOpenStackとJuniper機器で構成しました。

OpenStack では以下の設定を変える必要がありました。

  • VXLANインターフェースのTTL
    • OpenStackの設定で変更することができます
  • VXLANインターフェースのマルチキャストグループ
    • デフォルトではリンクローカルの 224.0.0.0/4 になっているので別のものに変更する
  • VXLANのポート番号
    • Juniperの機器はVXLANのポート番号として4789を使うのですが、Linuxのデフォルトは8742になっています
    • Linuxのカーネルパラメータで変更することができます

これらの経験から、TTLの変更を問題にすることを思いつきました。また、VyOSでVXLANを行うにあたって、マルチキャストルーティングができなさそうなことが検証段階で分かったので、それもトラブルとして加えました。